home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gold Medal Software 2
/
Gold Medal Software Volume 2 (Gold Medal) (1994).iso
/
prog
/
asm_0_m.arj
/
HBUILD16.ASM
< prev
next >
Wrap
Assembly Source File
|
1986-04-07
|
21KB
|
653 lines
TITLE HBUILD VERSION 1.60 16 December 1985
Page ,132
COMMENT #
HBUILD VERSION 1.60
This is a universal help program engine that enables an indexed
help program to be constructed from the HBUILD.COM file and a
suitably formatted text file.
The text of the help file which is used as input to this program
must be formatted according to a set of exact criteria. It is
important that no errors be made in the layout, as, while I have
included some error trapping, it is not totally bulletproof.
The first character to appear in the file is used by the program
as the separation character that it will look for in the rest of the
help file to indicate the end of a piece of text. This should be a
character that you will NOT use anywhere else in the help text.
I usually use the "happy face" (^A = ASCII 01) which my word processor
allows me to insert in a text file. The separation character must
appear as the first character in the help file followed immediately
by a CR and LF. The next character, again immediately followed by a
CR and LF is the exit character. This is the character which when
typed in response to any prompt and followed by a RETURN will exit
the program.
The format of the help file is as follows (using @ as the separation
character and * as the exit character, so they will display easily on
your word processor) :
@
*
MENU
User prompt for the first screen (placed on line 25)
This will be the text of the first screen which will contain
a list of help topics that can be requested. The data on this
screen is for user information only. The program doesn't use
anything here for index purposes. You may write any text here.
Other screens can be used as sub-menu
This is a list of commands:
COMMAND 1
COMMAND 2
etc ...
@
COMMAND 1
User prompt that appears on COMMAND 1 topic screen on line 25
\70 COMMAND 1 TITLE IN REVERSE VIDEO \07
This is the help text for "COMMAND 1" which may be up to 24 lines of data
starting at the line immediately follwing the 9 characters of "COMMAND 1".
@
COMMAND 2
User prompt that appears on COMMAND 2 topic screen on line 25
\01 COMMAND TWO \07
This is the help text for "COMMAND 2", whose title is this time shown as
underlined on a monochrome screen, or in blue on a color screen. This will
be the last command as it is followed by two separation characters on separate
lines.
@
@
Each command that is to be recognised by the help program MUST
occupy exactly 9 characters (pad on the right with blanks as needed),
be in UPPER CASE and be followed immediately by a CR and an LF.
The prompt for that help screen, which will be located on line 25,
follows immediately after the command, and should be 70 characters or
less. The help text immediately follows the prompt and may be up to 24
screen lines long. The text can contain embedded codes to change the
attribute of the characters being written. These are entered with a
backslash followed by TWO (must be two) hex digits which specify the
color/attribute of the characters which follow, until a new embedded
code appears. For example \70 TITLE \07 if it appeared in the help
text would display "TITLE" and the spaces either side of it in reverse
video, and subsequent text in regular video. A backslash character
can be inserted in the text using \\. Tabs are expanded and CR/LF
combinations are properly interpreted. The whole help text MUST be
terminated with TWO separation characters following each other on
separate lines. Note that the commands MUST be placed in the help file
in alphabetical order, if entries are going to be able to be found
where the entry characters are the same e.g. the command PRINT will
only be found if it preceeds the command PRINTER in the help text.
To make the help program from the help text, run HBUILD with the
following syntax:
HBUILD * [D:][PATH]HELPTEXT.EXT [D:][PATH]PROGNAME.COM
This will cause HBUILD to load the file HELPTEXT.EXT into memory,
index the commands and then, if there are no errors in the format
of the help text, write a file called PROGNAME.COM. If drive and
path are not specified then HBUILD will use the default drive and
directory.
PROGNAME.COM then contains the HBUILD "help engine" with the indexed
contents of HELPTEXT.EXT attached to it in the same file. To use
PROGNAME.COM, simply type :
PROGNAME [TOPIC]
at the DOS prompt, and you will be presented with the help screen
indexed to the command TOPIC (if it was included on the DOS command
line). If the help topic was not included on the command line, or the
name supplied does not appear in the index in PROGNAME, then you will
be presented with the screen defined at the head of the help text,
which should include a list of available commands.
The command interpreter will match on less than the total number
of characters in the command typed in at the prompt (or at the
command line), and will find the FIRST command that matches those
characters input; case is ignored. For example if the help text
contains the commands DISKCOMP and DISKCOPY, then the user input
DISKC will find DISKCOMP (assuming the help text had them in
alphabetical order). The user input of DISKCOP will find DISKCOPY.
To terminate the program you can press the ENTER key with no input.
Note that PROGNAME.COM contains the same program code as the
original HBUILD.COM file, so if you want, you could use PROGNAME
to update itself with a command like:
PROGNAME * HELPTEXT.MOD PROGNAME.COM
David Gwillim
1414 N. Catalina Street
Los Angeles CA 90027
16 December 1985
#
;
IF1
%OUT ************
%OUT * Pass One *
%OUT ************
ENDIF
IF2
%OUT
%OUT ************
%OUT * Pass Two *
%OUT ************
ENDIF
LF EQU 0AH
CR EQU 0DH
CRTMode EQU 449H ;ROM BIOS data area address
MaxSize EQU 65400 ;Base figure for help text size
; computation (allows 135 bytes
; for stack space)
Cseg SEGMENT
ASSUME CS:Cseg,DS:Cseg,ES:Cseg,SS:Cseg
ORG 100H
Start: Mov AH,30H ;Check DOS version
Int 21H
Cmp AL,2 ;Version 2 or greater?
Jnl H00
Mov DX,Offset BadDos ;Print wrong DOS message
Call PText
Mov AX,4C01H ;Set error code & terminate process
Int 21H
H00: Sub AX,AX ;Make a zero
Mov DS,AX ;Point to ABS0 segment
Mov SI,CRTMode ;Point to CRTMode byte
Lodsb
Cmp AL,7 ;Mode 7 = Monochrome screen?
Jne H0 ; if no, use color default
Mov ScrnAdd,0B000H ;Point to monochrome screen memory
H0: Push CS
Pop DS
Mov SI,81H ;Point to DOS command tail
H1: Lodsb
Cmp AL,' ' ;Skip any blanks
Je H1
Cmp AL,'*' ;Check for build option
Jne H2
Jmp BuildHelp ;We are making a help file
H2: Cmp AL,CR ;Any command tail?
Je H5 ;If no, go interactive
Mov DI,Offset Cmd ;Place to store command tail
Mov CX,9 ;Transfer 9 characters maximum
H3: Cmp AL,CR ;Transfer command tail
Je H4
Inc CmdLen
Stosb
Lodsb
Loop H3
H4: Call GC0 ;Jump into middle of GetCmd
Jmp H8 ;Display help text
H5: Mov DX,Current ;Select current screen
H6: Call PHelp ;Display help text
H7: Call GetCmd ;Get next command
Cmp CmdLen,0 ;Just a <RETURN> entered?
Je H5
Cmp CmdLen,1 ;Single character input line?
Jne H8 ; if so, exit program
Mov AL,Cmd ;What's the character that was input?
Cmp AL,ExitChr ;Is it the exit character?
Jne H8
Call ClrScr ;Clean up the screen before we leave
Mov AX,4C00H ;Set error code & terminate process
Int 21H
H8: Call GetMatch ;Find offset to help text
Cmp DX,0 ;Help text found?
Je H5 ;If not get another command
Mov Current,DX ;Command found, print it
Jmp H6 ;Do it all over again
; Clear screen
%OUT - ClrScr
ClrScr proc near
Mov BH,07 ;Clear screen with NORMAL attribute
MOV AX,0600H ; using "scroll active page up"
MOV CX,0 ; Upper left corner coords (0,0)
MOV DX,184FH ; Lower right corner coords (79,24)
INT 10H
MOV AH,2 ;Set cursor position
MOV BH,0 ;Page 0
MOV DX,0H ;Coords (0,0)
INT 10H
Mov ScrnPos,0 ;Point to beginning of the screen
RET
ClrScr endp
; Get the input command from the user
%OUT - GetCmd
GetCmd proc near
Mov DI,Offset CmdLen ;Initialize buffer to zeros
Mov AL,0
Mov CX,10
Rep Stosb
Mov DX,Offset CmdBuff ;Point to command input buffer
Mov AH,0AH ;Request edited input from DOS
Int 21H
GC0: Sub CX,CX ;Zero out CX
Mov CL,CmdLen ;Get input command length
Inc CX ;To permit handling null input
Mov SI,Offset Cmd ;Point to input command
Mov DI,SI ; for Lodsb and Stosb
GC1: Lodsb ;Get the next char from Cmd string
Cmp AL,'a' ;Upper case any lower case characters
Jl GC2
Cmp AL,'z'
Jg GC2
And AL,5FH
Cmp AL,CR ;End of input line?
Jne GC2
Mov AL,0 ;Terminate input with a 0 byte
GC2: Stosb
Loop GC1
Ret
GetCmd endp
; Print prompt for next command
%OUT - PPrompt
;Entry: DX contains offset to prompt string terminated in a 0 byte
PPrompt proc near
Mov ScrnPos,3840 ;Point to cursor position (0,24)
Call FText ;Print the prompt
Push DX ;Save returned pointer to help text
MOV BH,0 ; on page 0
MOV DH,18H ; to row 24
Mov AX,ScrnPos ;Get last screen location printed + 1
Sub AX,3840 ;Get # bytes into row 24
Shr AX,1 ;Divide by 2 to get cursor position
Mov DL,AL ; and put cursor there
MOV AH,2 ;Set cursor position
INT 10H
Mov ScrnPos,0 ;Point to the top of the screen again
Pop DX ;Restore pointer to help text
RET
PPrompt endp
%OUT - GetMatch
GetMatch proc near
Mov BX,HelpTxt ;Point to start of command table
Mov DX,0 ;Initialize DX
GM1: Cmp BX,0 ;Pointer to next command in table = 0?
Je GM3 ;if so, we are at the end of the table
Mov DI,BX ;Store start offset of command
Sub CX,CX ;Zero out CX
MOV CL,CmdLen ;Retrieve length of entered command
MOV SI,Offset Cmd ;Point to entered command
REPZ CMPSB ;Compare them
Jne GM2 ;If they weren't equal, try next cmd
Add BX,11 ;Jump over the command and pointer
MOV DX,BX ;This is the address of the prompt
GM2: CMP DX,0 ;Was there a match?
Jne GM3 ;If yes, then return
Mov BX,[BX+9] ;Get pointer to start of next command
Jmp GM1 ;Go check for a match with it
GM3: RET
GetMatch endp
%OUT - PHelp
PHelp proc near
PUSH DX ;Save the offset to the prompt
CALL ClrScr ;Clear the screen
POP DX ;Restore the offset to the prompt
Call PPrompt ;Print prompt for next command
Inc DX ;Point DX to help text
CALL FText ;Display the help text
PH1: RET
PHelp endp
;Print a piece of text
;Entry: DX points to start of text which is terminated in a 0 byte
;Exit : DX points to byte following 0 terminating byte
%OUT - FText
FText proc near
Mov SI,DX ;Point to text string with SI
Mov DI,ScrnPos ;Pick up the current screen position
Push ES ;Save ES
Mov ES,ScrnAdd ;Point ES to current screen memory
Mov AH,7 ;Default attribute
Mov CX,0 ;Start in column 0
PutScr: Lodsb ;Get byte from Buffer
Cmp AL,0 ;End of text?
Je Out
Cmp AL,'\' ;Is this a change of attribute
Jne L3
Call GetAttrib ;Read the next byte as new attribute
Jmp PutScr
L3: Cmp AL,CR ;Is it a CR
Jne L3A
Call Pad ;If so pad to end of line with blanks
Jmp PutScr
L3A: Cmp AL,9 ;Is it a tab character
Jne L4
Call FExpandTab ;If so, expand it (8 space column)
Jmp PutScr
L4: Cmp AL,LF
Je PutScr ;Ignore line feeds
ToScr: Stosw
Inc CH ;Keep track of column position
Jmp PutScr
Out: Mov ScrnPos,DI ;Store screen position
Pop ES ;Restore ES register
Mov DX,SI ;Return next position in text
Ret
FText endp
%OUT - FExpandTab
FExpandTab proc near
Push AX ;Save current attribute
Cmp CH,71 ;Are we in column 72 or more?
Jg FET2 ; if so just do a CR,LF
Mov AX,CX ;Put the column position in AL
XChg AH,AL
Sub AH,AH
Cmp AL,0 ;Make sure no divide by zero!
Je FET1
Div Eight ;Find out how far past last tab col
FET1: Xchg AH,AL ;Compute number of spaces to next
Mov AH,8
Sub AH,AL
Add CH,AH ;Keep track of line position
Mov CL,AH ;Number of spaces to print
Pop AX ;Get attribute byte
Push CX ;Save current value of line pos
Sub CH,CH ;Store count of spaces to display
Mov AL,' ' ;Space character
Rep Stosw ;Write to the screen
Pop CX ;Restore CX
Ret
FET2: Pop AX
Call Pad ;Pad line out to 80 columns
Ret
FExpandTab endp
%OUT - Pad
Pad Proc Near
Mov CL,80
Sub CL,CH ;Compute how many columns left
Je EndPad ;If zero we are in column 80.
Sub CH,CH ;So we can add CL to DI
Shl CX,1 ;Double CX to allow for attribute byte
Add DI,CX ;Pad columns to 80 by incrementing DI
EndPad: Sub CH,CH ;Reset column position counter to 0
Ret
Pad Endp
%OUT - GetAttrib
GetAttrib proc near
Push CX ;Save CX register
Push AX ;Save current attribute in AH
Sub AH,AH ;Start with 0 in AH
Mov CX,2 ;Accept 2 hex digits only
GA1: Lodsb ;Treat next character as attribute
Cmp AL,'\'
Je Literal ;Another \ treat as a literal char
Sub AL,30H ;Make ASCII digit binary
Jl GAOut ;Check if too low
Cmp AL,9
Jle GA2
And AL,5FH ;It wasn't 0 - 9 so upper case it
Sub AL,7 ;Make A - F into binary 10 - 15
Cmp AL,10 ;Less than A?
Jl GAOut ;Too low for A - F
Cmp AL,15 ;Greater than F?
Jg GAOut
GA2: Add AH,AL ;Accumulate hex digit
Cmp CX,2 ;Is this the first digit
Jne GA3
Push CX ;First hex digit so multiply by 16
Mov CL,4
Shl AH,CL
Pop CX
Loop GA1 ;Get the 2nd digit
GA3: Pop CX ;Throw away saved AX register
Pop CX ;Restore original CX register
Mov AL,0 ;Signify satifactory conversion
Ret ;AH contains new character attribute
GAOut: Pop AX ;If get here was an invalid hex number
Pop CX ; or a literal '\'
Ret
Literal:
Pop AX ;Restore registers
Pop CX
Stosw ;Put a \ to the screen
Inc CH ;Keep track of column position
Ret
GetAttrib Endp
%OUT - BuildHelp
BuildHelp:
Call GetNames ;Get the file names for build
Mov DX,Offset Author ;Print copyright
Call PText
Mov DX,Offset BHMsg ;Tell user we are doing build
Call PText
Call LoadTxt ;Load help text into memory
Call SaveFile ;Index the text & save it as a pgm
Mov DX,Offset BHDone ;Tell user we are donw
Call PText
Mov AX,4C00H ;Set error code & terminate process
Int 21H
;Print a piece of text
;Entry: DX points to start of text which is terminated in a 0 byte
%OUT - PText
PText proc near
MOV SI,DX ;Pointer to text start
PT1: Lodsb
Cmp AL,0 ;Are we at the end of the text?
Je PT3
; Cmp AL,9 ;Tab character
; Jne PT2
; Call ExpandTab ;Expand the tab to spaces
; Jmp PT1
PT2: Mov BL,7 ;Normal foreground color
Mov AH,0EH ;Write teletype function
Int 10H
Jmp PT1
PT3: RET
PText endp
%OUT - GetNames
GetNames proc near
Mov DI,Offset InName ;Point to 1st name buffer
GN1: Lodsb ;Skip any leading spaces
Cmp AL,' '
Je GN1
GN2: Cmp AL,CR ;End of command tail
Je GNErr ; if so error - no 2nd name
Cmp AL,' ' ;Space means end of 1st name
Je GN3
Stosb ;Store the character in name buffer
Lodsb
Jmp GN2 ;Back for more characters
GN3: Mov DI,Offset OutName ;Point to 2nd name
GN4: Lodsb ;Get next character
Cmp AL,' ' ;Skip any leading spaces
Je GN4
GN5: Cmp AL,CR ;End of command tail
Je GN6
Cmp AL,' '
Je GN6
Stosb
Lodsb
Jmp GN5
GN6: Ret
GNErr: Mov DX,Offset BHErr
Call PText
Pop AX ;Clean up the stack
Mov AX,4C01H ;Set error code & terminate process
Int 21H
GetNames endp
%OUT - LoadTxt
LoadTxt proc near
Mov DX,Offset InName ;Point to file name
Mov AL,0 ;read access
Mov AH,3dH ;Open the file
Int 21H
Jc LTErr ;If we get an error, report it
Mov Handle,AX ;Store the returned handle
Mov BX,AX ;File handle for read file
Mov DX,Offset SepChar ;Address of file buffer start
Mov CX,MaxSize ;Calculate max number of bytes to read
Sub CX,EndPgm ;allowing 128 bytes for .COM pgm stack
Mov MaxBytes,CX ;Save the requested number of bytes
Mov AH,3FH ;Read file/device function
Int 21H
Jc LTErr ;Report any error
Cmp AX,MaxBytes ;Same read as asked for?
Je LTLenErr ;Almost certainly, file too long
Mov BytesRead,AX ;Store number of bytes read in
Mov BX,Handle ;Close file
Mov AH,3EH ;Close file function
Int 21H
Ret
LTErr: Mov DX,Offset LoadErr ;Print error message
Call PText
Pop AX ;Clean up the stack
Mov AX,4C01H ;Set error code & terminate process
Int 21H
LTLenErr:
Mov DX,Offset LenErr ;Print error message - file too long
Call PText
Pop AX ;Clean up the stack
Mov AX,4C01H ;Set error code & terminate process
Int 21H
LoadTxt endp
%OUT - SaveFile
SaveFile proc near
Mov Current,Offset Buffer + 11 ;Store pointer to first screen
Mov DI,Offset Buffer + 9 ;Initialize pointer for cmd address
Mov SI,Offset Buffer ;Point to start of text
SF1: Lodsb ;Main loop for commands starts here
Cmp AL,SepChar ;End of help text file?
Je SF6
Mov CX,9
SF2: Lodsb
Cmp AL,CR ;End of a command?
Je SF3
Loop SF2
Jmp SFCErr ;We fell out of loop = error
SF3: Cmp CX,1 ;We should have been on last iteration
Jne SFCErr ;If not, error in command length
Mov DI,SI ;Point DI to storage for next cmd addr
Dec DI
SF4: Lodsb ;Look for end of prompt string
Cmp AL,CR ;End of help text?
Jne SF4
Mov byte ptr [SI-1],0 ;Terminate prompt with 0 byte
SF5: Lodsb
Cmp AL,SepChar ;Look for end of help text
Jne SF5
Mov byte ptr [SI-1],0 ;Terminate text with 0 byte
Cmp byte ptr [SI],CR ;Should be a CR, error if not
Jne SFTErr
Add SI,2 ;Skip past CRLF following SepChar
Mov [DI],SI ;SI points to next command, store it
Jmp SF1 ;Keep indexing help text
SF6: Mov word ptr [DI],0 ;Signify the end of the help text
Mov byte ptr [SI-1],0 ;Terminate the text with 0 byte
Mov LastOfs,SI ;Store end of memory used
; Now we have indexed the help text, write it plus the "engine" to disk
Mov DX,Offset OutName ;Open output file
Mov CX,0 ;Normal file attribute
Mov AH,3CH ;Create file function
Int 21H
Jnc SF7
Mov DX,Offset SFErr1 ;Report any error
Jmp SFErr ;In case of error
SF7: Mov Handle,AX ;Store handle
Mov BX,AX ;Handle for write
Mov DX,100H ;Write whole pgm to disk file
Mov CX,LastOfs ;Last memory location used
Sub CX,DX ;Allow for PSP in byte count
Mov AH,40H ;Write file function
Int 21H
Jnc SF8
Mov DX,Offset SFErr2 ;Report any error
Jmp SFErr
SF8: Mov BX,Handle ;Close file
Mov AH,3EH ;Close file function
Int 21H
Ret
SFErr: Call PText
Pop AX ;Clean up the stack
Mov AX,4C01H ;Set error code & terminate
Int 21H
SFCErr: Mov byte ptr [SI],0 ;Terminate text with 0 byte
Push DI ;Save the pointer to start of command
Mov DX,Offset HCErr ;Print 'Error in command ... '
Call PText
Pop DI
Mov DX,[DI] ;Get address to bad area
Call PText
Mov AX,4C01H ;Set error code & terminate
Int 21H
SFTErr: Push SI ;Save pointer to byte following error
Mov DX,Offset HTErr ;Print 'Error in text ... '
Call PText
Pop SI ;Recover pointer to bad byte
Mov Byte ptr [SI+60],0 ;Limit text display to one line
Mov DX,SI ;Get address to bad area
Call PText
Mov AX,4C01H ;Set error code & terminate
Int 21H
SaveFile endp
%OUT - Variables
Eight Db 8
BadDos Db 'HBUILD needs DOS version 2.0 or greater',CR,LF,0
BHMsg Db 'Building Help Program',CR,LF,LF,0
BHErr Db 'USAGE:',CR,LF,9
DB 'HBUILD * [D:][Path]HelpFile.Ext [D:][Path]OutFile.COM',CR,LF,0
BHDone Db 'Build Help successfully completed',CR,LF,0
LoadErr Db 'Error: Cannot read input file',CR,LF,0
LenErr Db 'Error: Help file too long to use',CR,LF,0
SFErr1 Db 'Error: Cannot open output file',CR,LF,0
SFErr2 Db 'Error: Cannot close output file',CR,LF,0
HTErr Db 'Error: Misplaced separation character prior to -->',CR,LF,0
HCErr Db 'Error: Help command not 9 characters long --> ',0
InName Db 64 Dup(0)
OutName Db 64 Dup(0)
ScrnAdd Dw 0B800H ;Default of color graphics screen
ScrnPos DW 0 ;Position in screen buffer
Handle Dw 0
BytesRead Dw 0 ;Number of bytes read from help text
MaxBytes Dw 0 ;Maximum number of bytes in Buffer
LastOfs Dw 0 ;Last offset used by help text
Current Dw Offset Null ;Current help screen address
CmdBuff Db 9 ;User input command buffer
CmdLen Db 0 ; as per DOS function 0AH layout
Cmd Db 9 Dup(0)
Null Db '\70 PRESS RETURN \07',0,0
Author Db 'HELP BUILD Version 1.6 - 16 December 1985',CR,LF
Db 'Copyright (C) 1985 by David Gwillim ',CR,LF,0
HelpTxt Dw Offset Buffer
EndPgm Dw $
SepChar Db 0 ;Separation character for help file
Db 2 Dup(0) ;Space for CRLF following SepChar
ExitChr Db 0 ;Exit character
Db 2 Dup(0) ;Space for CRLF following ExitChr
Buffer Db 0 ;Start of help text proper
Cseg Ends
End Start